<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
<script>
    //有8个图片资源的url，已经存储在数组urls中。

    // urls类似于['https://image1.png', 'https://image2.png', ....]

    // 而且已经有一个函数function loadImg，输入一个url链接，返回一个Promise，该Promise在图片下载完成的时候resolve，下载失败则reject。

    // 但有一个要求，任何时刻同时下载的链接数量不可以超过3个。

    // 请写一段代码实现这个需求，要求尽可能快速地将所有图片下载完成。
    var urls = [
        "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting1.png",
        "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting2.png",
        "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting3.png",
        "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting4.png",
        "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting5.png",
        "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn6.png",
        "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn7.png",
        "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn8.png",
    ];
    function loadImg(url) {
        return new Promise((resolve, reject) => {
            const img = new Image();
            img.onload = function () {
                setTimeout(()=>{
                    console.log("一张图片加载完成");
                    resolve(img);
                },1000)
            };
            img.onerror = function () {
                reject(new Error('Could not load image at' + url));
            };
            img.src = url;
        })
    }

    /**
     * 并发控制函数，限制同时执行的任务数量
     * @param {number} num - 最大并发任务数
     * @returns {Promise<Array>} 返回Promise对象，解析值为结果数组（包含每个URL的处理结果或错误）
     */
    async function concurrent(num){
        // 初始化结果数组（长度与urls数组相同）
        const result = new Array(urls.length)
        // 存储当前正在运行的任务（Promise对象）
        const running = []

        // 遍历所有URL
        for(let i = 0;i < urls.length;i++){
            // 当运行任务数达到并发上限时，等待任意任务完成
            if(running.length >= num){
                await Promise.race(running)
            }

            /**
             * 创建任务Promise链：
             * 1. 加载图片
             * 2. 成功/失败时记录结果到对应索引位置
             * 3. 任务完成后从运行队列移除自身
             */
            const p = loadImg(urls[i]).then(res=>{
                result[i] = res
            }).catch((e)=>{
                result[i] = e
            }).finally(()=>{
                const index = running.indexOf(p)
                if(index !== -1){
                    running.splice(index,1)
                }
            })

            // 将新任务加入运行队列
            running.push(p)
        }

        // 等待所有剩余任务完成
        await Promise.all(running)
        return result
    }

    // 调用示例：最大并发数为3
    concurrent(3).then(res=>{
        console.log(res)
    })

</script>
</html>